package base2

import (
	"encoding/json"
	"fmt"
	"runtime"
	"strings"
)

func NewBsfError(msg string) *BsfError {
	return NewBsfError2(msg, nil)
}

func NewBsfError2(msg string, error error) *BsfError {
	return &BsfError{Msg: msg, BaseError: error, Trace: trace()}
}

func NewBsfBizError(msg string) *BsfBizError {
	return NewBsfBizError2(msg, nil)
}

func NewBsfBizError2(msg string, error error) *BsfBizError {
	return NewBsfBizError3(-1, msg, error)
}

func NewBsfBizError3(code int, msg string, error error) *BsfBizError {
	err := &BsfBizError{}
	err.Code = code
	err.Msg = msg
	err.BaseError = error
	err.Trace = trace()
	return err
}

type BsfError struct {
	Msg       string
	BaseError error
	Trace     []string
}

func (c *BsfError) Error() string {
	return fmt.Sprintf("[异常信息]%v\r\n[异常来源]%v\r\n[堆栈信息]%v\r\n", c.Msg, c.BaseError, strings.Join(c.Trace, "\r\n"))
}
func (c *BsfError) ToJson() string {
	return toJson(c)
}
func (c *BsfError) ToJsonNoTrace() string {
	data := CoreUtil.ReflectStructToMap(c)
	delete(data, "Trace")
	return toJson(data)
}

func trace() []string {
	var ss []string
	for i := 1; ; i++ { // Skip first frame (this function)
		_, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		ss = append(ss, fmt.Sprintf("%s:%d", file, line))
	}
	return ss
}

func toJson(err any) string {
	jsonBytes, _ := json.Marshal(err)
	return string(jsonBytes)
}

type BsfBizError struct {
	Code int
	BsfError
}
